#!/bin/bash -e

######################################################################
# Building devkitvb requires the following packages to be installed: #
# gcc, flex, bison, tar, bzip2, gzip, make, patch, curl              #
#                                                                    #
# The following libraries are also required (for GCC):               #
# libgmp, libmpfr, libmpc                                            #
#                                                                    #
# makeinfo is required for binutils and newlib; it's a part of the   #
# texinfo package.                                                   #
#                                                                    #
# To build, just run this script! It will download the source        #
# distributions, configure, and build them.  You might also want to  #
# modify the "Configuration section just below ...                   #
######################################################################

### FIXME:
#   Explode if configure fails
#   Apply patches

### Configuration
TARGET="v850-elf"
PREFIX="${HOME}/${TARGET}"
PATH="${PATH}:${PREFIX}/bin"
MAKE=$(which make)


### Source distributions
BINUTILS="binutils-2.20.1"
GCC="gcc-4.5.0"
NEWLIB="newlib-1.18.0"
GDB="gdb-7.1"

GCC_VER=${GCC##*-}
GCC_CORE="gcc-core-${GCC_VER}"

FILE_BINUTILS="${BINUTILS}.tar.bz2"
FILE_GCC="${GCC_CORE}.tar.bz2"
FILE_NEWLIB="${NEWLIB}.tar.gz"
FILE_GDB="${GDB}.tar.bz2"

DL_BINUTILS="http://ftpmirror.gnu.org/binutils/${FILE_BINUTILS}"
DL_GCC="http://ftpmirror.gnu.org/gcc/${GCC}/${FILE_GCC}"
DL_NEWLIB="ftp://sources.redhat.com/pub/newlib/${FILE_NEWLIB}"
DL_GDB="http://ftpmirror.gnu.org/gdb/${FILE_GDB}"


### Utility functions
check_app() {
    if [ -z $(which $1) ]; then
        echo "$1 not found"
        exit 1
    fi
}

get_script_dir() {
    path=$(readlink -f $1 2>&1)
    if [ -n "$(echo ${path} | grep 'illegal option -- f')" ]; then
        # OSX readlink is broke ... try Python
        check_app "python"
        path=$(python -c 'import os,sys;print os.path.realpath(sys.argv[1])' $1)
    fi

    echo $(dirname ${path})
}

apply_patch() {
    if [ ! -f ".patch-$1" ]; then
        patch -p1 <"../patches/$1.patch"
        touch ".patch-$1"
    fi
}


### Targets
download() {
    FILE=${2##*/}
    if [ ! -f "packages/${FILE}" ]; then
        echo "$1..."
        mkdir -p packages
        curl -L --progress-bar -o "packages/${FILE}" $2
        echo
    fi
}

all() {
    ### Check build environment
    echo
    echo "Checking build environment..."
    check_app "bison"
    check_app "bzip2"
    check_app "curl"
    check_app "flex"
    check_app "gcc"
    check_app "gzip"
    check_app "make"
    check_app "makeinfo"
    check_app "patch"
    check_app "tar"


    ### Download all source packages
    echo
    echo "Downloading source packages..."
    download ${BINUTILS} ${DL_BINUTILS}
    download ${GCC_CORE} ${DL_GCC}
    download ${NEWLIB} ${DL_NEWLIB}
    #download ${GDB} ${DL_GDB}


    ### Build binutils
    if [ ! -d ${BINUTILS} ]; then
        echo
        echo "Decompressing ${FILE_BINUTILS}..."
        tar xjf "packages/${FILE_BINUTILS}"
    fi
    echo
    echo "Building binutils..."
    mkdir -p build-binutils
    cd build-binutils
    if [ ! -f Makefile ]; then
        ../${BINUTILS}/configure --target=${TARGET} --prefix=${PREFIX} \
            --disable-werror
    fi
    ${MAKE} all install
    cd ..


    ### Build bootstrap GCC
    if [ ! -d ${GCC} ]; then
        echo
        echo "Decompressing ${FILE_GCC}..."
        tar xjf "packages/${FILE_GCC}"
    fi
    echo
    echo "Building gcc..."
    mkdir -p build-gcc
    cd build-gcc
    if [ ! -f Makefile ]; then
        args=""
        if [ $(uname) = "Darwin" ]; then
            # Assume dependencies were installed with macports
            args="--with-gmp=/opt/local --with-mpfr=/opt/local --with-mpc=/opt/local"
            LDFLAGS="-L/opt/local/lib ${LDFLAGS}"
        fi
        LDFLAGS="${LDFLAGS}" ../${GCC}/configure --target=${TARGET} --prefix=${PREFIX} \
            --without-headers --with-newlib --with-gnu-as --with-gnu-ld \
            ${args}
    fi
    ${MAKE} all-gcc install-gcc
    cd ..


    ### Build newlib
    if [ ! -d ${NEWLIB} ]; then
        echo
        echo "Decompressing ${FILE_NEWLIB}..."
        tar xzf "packages/${FILE_NEWLIB}"
    fi
    echo
    echo "Building newlib..."
    mkdir -p build-newlib
    cd build-newlib
    if [ ! -f Makefile ]; then
        ../${NEWLIB}/configure --target=${TARGET} --prefix=${PREFIX}
    fi
    ${MAKE} all install
    cd ..


    ### Build GCC again, this time with newlib
    echo
    echo "Rebuilding gcc with newlib..."
    cd build-gcc
    if [ ! -f Makefile ]; then
        ../${GCC}/configure --target=${TARGET} --prefix=${PREFIX} \
            --with-newlib --with-gnu-as --with-gnu-ld --disable-shared \
            --disable-libssp
    fi
    ${MAKE} all install
    cd ..


    ### HOORAY! We made it!
    echo
    echo "Done!"
}

uninstall() {
    echo
    echo "Uninstalling is not possible. :("
    echo
    echo "If you want to [naively] uninstall, try:"
    echo "  rm -rf ${PREFIX}"
}

clean() {
    echo "Cleaning..."
    rm -rf ${BINUTILS} ${GCC} ${NEWLIB} ${GDB} build-*
}


### Make sure we're in the build directory
cd $(get_script_dir $0)


### Process arguments
case "$1" in
    clean)
        clean
        ;;
    uninstall)
        uninstall
        ;;
    *)
        all
        ;;
esac
